﻿using System;
using System.Collections.Generic;
using System.Linq;
using Luna.Data.Accounting.Mappers;
using Luna.Data.Mappers;

namespace Luna.Data.Accounting
{
    public class AccountingDataProvider : LunaDataProvider, IAccountingDataProvider
    {
        public AccountingDataProvider()
        {
            DefineTypeCreation<INamedEntityData, NamedEntityData>();
            DefineTypeCreation<IAccountData, AccountData>();
            DefineTypeCreation<IOtherOperationData, OtherOperationData>();
            DefineTypeCreation<IAccountCreditCardData, AccountCreditCardData>();
        }

        #region Mappers
        public NamedEntityDataMapper AccountingCategoryMapper { get; set; }

        public AccountDataMapper AccountMapper { get; set; }

        public OtherOperationDataMapper OtherOperationMapper { get; set; }

        public CreditCardDataMapper CreditCardMapper { get; set; }
        #endregion

        #region Categories
        public IEnumerable<INamedEntityData> GetAllCategories()
        {
            return WrapperTransactional(T => AccountingCategoryMapper.GetAll(T));
        }

        public INamedEntityData GetCategory(Guid P_CategoryID)
        {
            return WrapperTransactional(T => AccountingCategoryMapper.Get(T, P_CategoryID));
        }

        public void SaveCategory(INamedEntityData P_Category)
        {
            WrapperTransactional(T => AccountingCategoryMapper.Save(T, P_Category));
        }

        public void DeleteCategory(Guid P_CategoryID)
        {
            WrapperTransactional(T => AccountingCategoryMapper.Delete(T, P_CategoryID));
        }
        #endregion

        #region Accounts
        public IEnumerable<IAccountData> GetAllAccounts()
        {
            return WrapperTransactional(T => AccountMapper.GetAll(T));
        }

        public IAccountData GetAccount(Guid P_CategoryID)
        {
            return WrapperTransactional(T => AccountMapper.Get(T, P_CategoryID));
        }

        public void SaveAccount(IAccountData P_Category)
        {
            WrapperTransactional(T => AccountMapper.Save(T, P_Category));
        }

        public void SaveAccount(IAccountData P_Account, IEnumerable<IOtherOperationData> P_Operations)
        {
            WrapperTransactional(T =>
            {
                AccountMapper.Save(T, P_Account);

                foreach (var L_Operation in P_Operations)
                {
                    OtherOperationMapper.Save(T, L_Operation);
                }

                foreach (var L_Item in OtherOperationMapper.GetAllByAccount(T, P_Account.PK))
                {
                    if (P_Operations.FirstOrDefault(x => x.PK == L_Item.PK) == null)
                    {
                        OtherOperationMapper.Delete(T, L_Item.PK);
                    }
                }
            });
        }

        public void DeleteAccount(Guid P_CategoryID)
        {
            WrapperTransactional(T =>
            {
                foreach (var L_Item in OtherOperationMapper.GetAllByAccount(T, P_CategoryID))
                {
                    OtherOperationMapper.Delete(T, L_Item.PK);
                }

                AccountMapper.Delete(T, P_CategoryID);
            });
        }
        #endregion

        #region Other operations
        public IEnumerable<IOtherOperationData> GetAllOtherOperations()
        {
            return WrapperTransactional(T => OtherOperationMapper.GetAll(T));
        }

        public IEnumerable<IOtherOperationData> GetAllOtherOperationsByAccount(Guid P_AccountID)
        {
            return WrapperTransactional(T => OtherOperationMapper.GetAllByAccount(T, P_AccountID));
        }

        public IOtherOperationData GetOtherOperation(Guid P_OperationID)
        {
            return WrapperTransactional(T => OtherOperationMapper.Get(T, P_OperationID));
        }

        public void SaveOtherOperation(IOtherOperationData P_OtherOperation)
        {
            WrapperTransactional(T => OtherOperationMapper.Save(T, P_OtherOperation));
        }

        public void DeleteOtherOperation(Guid P_OperationID)
        {
            WrapperTransactional(T => OtherOperationMapper.Delete(T, P_OperationID));
        }
        #endregion

        #region Metadata
        private const string _ID = "028A8839-94D0-4FD7-89F5-66BBEB1B9151";

        private const string _NAME = "Luna accounting data provider";

        public override Guid ID
        {
            get { return new Guid(_ID); }
        }

        public override string Name
        {
            get { return _NAME; }
        }
        #endregion

        #region Credit card
        public IEnumerable<IAccountCreditCardData> GetAllCreditCards()
        {
            return WrapperTransactional(T => CreditCardMapper.GetAll(T));
        }

        public IEnumerable<IAccountCreditCardData> GetAllCreditCardsByAccount(Guid P_AccountID)
        {
            return WrapperTransactional(T => CreditCardMapper.GetAllByAccount(T, P_AccountID));
        }

        public IAccountCreditCardData GetCreditCard(Guid P_CreditCardID)
        {
            return WrapperTransactional(T => CreditCardMapper.Get(T, P_CreditCardID));
        }

        public void SaveCreditCard(IAccountCreditCardData P_Card)
        {
            WrapperTransactional(T => CreditCardMapper.Save(T, P_Card));
        }

        public void DeleteCreditCard(Guid P_CardID)
        {
            WrapperTransactional(T => CreditCardMapper.Delete(T, P_CardID));
        }
        #endregion
    }
}
